package sbc.group1.lab1.alt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.concurrent.CopyOnWriteArrayList;


import sbc.group1.lab1.common.Car;

public class CarList implements Collection<Car>{
	
	private static class Iter implements Iterator<Car> {
		private final Iterator<Car> first;
		private final Iterator<Car> second;
		private Iterator<Car> active;
		
		private Iter(List<Car> unordered,
			PriorityQueue<Car> ordered) {
			this.first=ordered.iterator();
			this.second=unordered.iterator();
			this.active=this.first;
			if (active.hasNext()) {
				active=this.second;
			}
		}
		
		@Override
		public boolean hasNext() {
			if (active.hasNext()) {
				return true;
			}else {
				if (active==this.first) {
					active=this.second;
					return hasNext();
				}else {
					return false;
				}
			}
		}

		@Override
		public Car next() {
			return active.next();
		}

		@Override
		public void remove() {
			active.remove();
		
		}
	}
	
	private final List<Car> unordered = 
		new CopyOnWriteArrayList<Car>();
	private final PriorityQueue<Car> ordered=
		new PriorityQueue<Car>();
	
	public boolean put(Car car) {       
	    if (car.getOrder()==null) {
	    	return unordered.add(car);
	    }else {
	    	return ordered.add(car);
	    }
	}
	
	public boolean remove(Car car) {
	    if (car.getOrder()==null) {
	    	return unordered.remove(car);
	    }else {
	    	return ordered.remove(car);
	    }

	}

	public int size() {
		return ordered.size()+unordered.size();
	}

	public Iterator<Car> iterator() {
		return new Iter(unordered, ordered);
	}

	@Override
	public boolean add(Car e) {
		return put(e);
	}

	@Override
	public boolean addAll(Collection<? extends Car> c) {
		boolean changed = false;
		for (Car e : c) {
			if (add(e)) {
				changed=true;
			}
		}
		return changed;
	}

	@Override
	public void clear() {
		ordered.clear();
		unordered.clear();
	}

	@Override
	public boolean contains(Object o) {
		return ordered.contains(o) || unordered.contains(o);
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		Collection<Car> tmp = new ArrayList<Car>(ordered);
		tmp.addAll(unordered);
		return tmp.containsAll(c);
	}

	@Override
	public boolean isEmpty() {
		return unordered.isEmpty()&&ordered.isEmpty();
	}

	@Override
	public boolean remove(Object o) {
		return ordered.remove(o) || unordered.remove(o);
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		return ordered.remove(c) || unordered.remove(c);
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		boolean changed = ordered.retainAll(c);
		changed |= unordered.retainAll(c);
		return changed;
	}

	@Override
	public Object[] toArray() {
		Collection<Car> tmp = new ArrayList<Car>(ordered);
		tmp.addAll(unordered);
		return tmp.toArray();
	}

	@Override
	public <T> T[] toArray(T[] a) {
		Collection<Car> tmp = new ArrayList<Car>(ordered);
		tmp.addAll(unordered);
		return tmp.toArray(a);
	}
	
	public Car pollFirst(){
		Car c = ordered.poll();
		if(c == null){
			try{
			c = unordered.remove(0);
			}catch(IndexOutOfBoundsException ex){
				c = null;
			}
		}
		return c;
	}
	
	
}